<template>
  <!-- 查询区域 -->
  <el-form :inline="true" :model="queryDataSource" class="query-form">
    <el-form-item label="数据源名称">
      <el-input v-model="queryDataSource.name" placeholder="请输入数据源名称" clearable></el-input>
    </el-form-item>
    <el-form-item label="开始创建时间">
      <el-date-picker v-model="queryDataSource.startTime"
                      type="datetime"
                      placeholder="开始创建时间"
                      value-format="yyyy-MM-dd HH:mm:ss"
                      clearable />
    </el-form-item>
    <el-form-item label="结束创建时间">
      <el-date-picker v-model="queryDataSource.endTime"
                      type="datetime"
                      placeholder="结束创建时间"
                      value-format="yyyy-MM-dd HH:mm:ss"
                      clearable />
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="search">查询</el-button>
      <el-button type="info" @click="reset">重置</el-button>
    </el-form-item>
  </el-form>
  <el-divider/>
  <div class="op-btn">
    <el-button v-if="hasPermission('datasource:add')" type="primary"  class="btn" @click="addDataSource">新增数据源</el-button>
    <el-button v-if="hasPermission('datasource:delete')" type="danger" class="btn" @click="batchDelDataSource">批量删除</el-button>
  </div>

  <el-table
      :data="dataSourceList"
      style="width:100%"
      @selection-change="handleSelectionChange"
      class="custom-table"
      border
      stripe>
    <el-table-column type="selection" width="50" />
    <el-table-column type="index" label="序号" width="80" />
    <el-table-column prop="name" label="数据源名称" />
    <el-table-column prop="url" label="数据源URL" />
    <el-table-column prop="createTime" label="创建时间" />
    <el-table-column label="操作">
      <!-- 使用插槽 -->
      <template #default="scope">
        <!-- 编辑按钮 -->
        <el-button v-if="hasPermission('datasource:update')" type="primary" @click="edit(scope.row.id)" size="small">编辑</el-button>
        <!-- 删除按钮 -->
        <el-button v-if="hasPermission('datasource:delete')" type="danger" @click="del(scope.row.id)" size="small">删除</el-button>
      </template>
    </el-table-column>
  </el-table>
  <el-pagination background
                 layout="prev, pager, next, jumper, total"
                 :page-size="pageSize"
                 :total="total"
                 @current-change="handleCurrentChange"
                 class="pagination" />

  <!-- 新增数据源弹框 -->
  <el-dialog v-model="addDataSourceDialogVisible" :title="dailogTitle" width="35%" :close-on-click-modal="false">
    <el-form ref="dataSourceRefForm" :model="dataSource" label-width="110px" :rules="dataSourceRules">
      <el-form-item label="数据源名称" prop="name">
        <el-input v-model="dataSource.name"  clearable />
      </el-form-item>
      <el-form-item label="数据源URL" prop="url">
        <el-input v-model="dataSource.url" clearable />
      </el-form-item>
      <el-form-item label="用户名" prop="username">
        <el-input v-model="dataSource.username" clearable />
      </el-form-item>
      <el-form-item label="密码" prop="password">
        <el-input v-model="dataSource.password" clearable type="password" />
      </el-form-item>
      <div>
        测试连通性：<el-link :icon="Key" :underline="false" @click="testConnection"></el-link>
        <span v-if="testConnectionResult === '测试连接成功'" style="color: green; margin-left: 20px">{{ testConnectionResult }}</span>
        <span v-if="testConnectionResult !== '测试连接成功'" style="color: red; margin-left: 20px">{{ testConnectionResult }}</span>
      </div>
      <div style="margin-top: 10px">
        <span style="color: grey; margin-left: 20px">注意：当前只支持添加mysql动态数据源！！</span>
      </div>
    </el-form>

    <template #footer>
      <span class="dialog-footer">
        <el-button @click="addDataSourceDialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="dataSourceSubmit">提 交</el-button>
      </span>
    </template>
  </el-dialog>

</template>

<script>
import {DATA_SOURCE_PWD_ENCRYPT, PAGE_SIZE} from "../../contants/constants.js";
import {doDelete, doGet, doPost, doPut} from "../../http/httpRequest.js";
import CryptoJS from "crypto-js";
import {msgConfirm, msgTip} from "../../util/util.js";
import {Key} from "@element-plus/icons-vue";

const secretKey = CryptoJS.enc.Latin1.parse(DATA_SOURCE_PWD_ENCRYPT);
const iv = CryptoJS.enc.Latin1.parse(DATA_SOURCE_PWD_ENCRYPT);


export default {
  name: "DataSource",

  computed: {
    Key() {
      return Key
    }
  },

  inject:['reload'],

  data() {
    return {
      // 查询数据源数据
      queryDataSource: {},
      // 新增数据源数据
      dataSource:{},
      originalDataSource:{},
      // 数据源列表
      dataSourceList: [],
      pageSize: PAGE_SIZE,
      total: 0,
      selectedRows: [],
      dailogTitle: "",
      // 数据源连通性测试
      testConnectionResult: "",
      isTest: false,
      // 控制新增数据源对话框是否显示，false:不显示，true:显示
      addDataSourceDialogVisible: false,
      permissions:{}, // 权限
      dataSourceRules: {
        name: [
          { validator: this.validateDataSourceName, trigger: "blur"}
        ],
        url: [
          { validator: this.validateDataSourceURL, trigger: "blur" }
        ],
        username: [
          { required: true, message: "请输入用户名", trigger: "blur" }
        ],
        password: [
          { required: true, message: "请输入密码", trigger: "blur" }
        ]
      }
    };
  },
  watch: {
    'dataSource.url' : 'clearTestConnectionResult',
    'dataSource.username' : 'clearTestConnectionResult',
    'dataSource.password' : 'clearTestConnectionResult',
  },
  methods: {
    clearTestConnectionResult() {
      this.testConnectionResult = "";
    },
    search() {
      this.getData(1);
    },
    reset() {
      this.queryDataSource = {};
      this.getData(1);
    },
    getData(current) {
      doGet("/system/ds/list", {
        pageNum: current,
        name: this.queryDataSource.name,
        startTime: this.queryDataSource.startTime,
        endTime: this.queryDataSource.endTime
      }).then(resp => {
        if (resp.data.code === 200) {
          this.dataSourceList = resp.data.data.list;
          this.total = resp.data.data.total;
          this.pageSize = resp.data.data.pageSize;
        }
      });
    },
    /* 当页码改变后获取不同页的数据 */
    handleCurrentChange(current) {
      this.getData(current);
    },
    handleSelectionChange(selection) {
      this.selectedRows = selection.map(item => item.id);

    },
    addDataSource() {
      this.addDataSourceDialogVisible = true;
      this.dailogTitle = "新增数据源";
      this.dataSource = {};
      this.testConnectionResult = "";
    },
    batchDelDataSource() {
      if (this.selectedRows.length === 0) {
        msgTip("请选择要删除的数据源", "warning");
        return;
      }
      // 批量删除数据源逻辑
      msgConfirm("确定要删除吗？").then(() => {
        const ids = this.selectedRows.join(",");
        doDelete("/system/ds/batchDel", {ids: ids}).then(resp => {
          if (resp.data.code === 200) {
            msgTip("删除成功", "success");
            this.reload();
          } else {
            msgTip("删除失败，请稍后再试", "error");
          }
        });
      }).catch(() => {
        msgTip("取消了删除", 'warning');
      })
    },
    edit(id) {
      // 编辑数据源逻辑
      doGet("/system/ds/" + encodeURI(id)).then(resp => {
        if (resp.data.code === 200) {
          this.dataSource = resp.data.data;
          this.originalDataSource = {...resp.data.data};
          this.testConnectionResult = "";
          this.dailogTitle = "编辑数据源";
          this.addDataSourceDialogVisible = true;
        } else {
          msgTip("数据源获取失败，请稍后再试", "error");
        }
      });
    },
    del(id) {
      // 删除数据源逻辑
      msgConfirm("确定要删除吗？").then(() => {
        doDelete("/system/ds/" + encodeURI(id)).then(resp => {
          if (resp.data.code === 200) {
            msgTip("删除成功", "success");
            this.reload();
          } else {
            msgTip("删除失败，请稍后再试", "error");
          }
        });
      }).catch(() => {
        msgTip("取消了删除", 'warning');
      })
    },

    // 新增数据源名称校验
    validateDataSourceName(rule, value, callback) {
      if (!value) {
        callback(new Error("请输入数据源名称"));
      } else if(!this.dataSource.id) {
        // 新增时校验
        doGet("/system/ds/checkName", {
          name: value
        }).then(resp => {
          if (resp.data.code === 200) {
            if (resp.data.data) {
              callback(new Error("数据源名称已存在,请更换"));
            } else {
              callback();
            }
          }
        }).catch(() => {
          callback(new Error("数据校验失败，请稍后再试"));
        })
      } else if(this.dataSource.id) {
        // 编辑时校验
        doGet("/system/ds/updateCheckName", {
          name: value,
          id: this.dataSource.id
        }).then(resp => {
          if(resp.data.data) {
            callback(new Error("数据源名称已存在，请更换"))
          } else {
            callback();
          }
        }).catch(() => {
          callback(new Error("数据校验失败，请稍后再试"))
        })
      }
    },

    // 新增数据源URL校验
    validateDataSourceURL(rule, value, callback) {
      const mysqlUrlRegex = /^jdbc:mysql:\/\/([a-zA-Z0-9.+-/]+)(:\d+)?\/[a-zA-Z0-9._+-/]+(\?[a-zA-Z0-9._+-/]+=[a-zA-Z0-9._+-/]+(&[a-zA-Z0-9._+-]+=[a-zA-Z0-9._+-/]+)*)?$/
      if(!value) {
        callback(new Error("请输入数据源URL"));
        return;
      }
      if(!mysqlUrlRegex.test(value)) {
        callback(new Error("请输入有效的mysql连接字符串"));
      } else {
        callback();
      }
    },

    // 测试数据源连接逻辑
    testConnection() {
      this.$refs.dataSourceRefForm.validate(valid => {
        if(valid) {
          const originalPassword = this.dataSource.password;
          // 如果是新增时或者更新时修改过密码才需要进行密码加密
          if(!this.dataSource.id || this.originalDataSource.password !== this.dataSource.password) {
            // 密码进行加密
            this.dataSource.password = CryptoJS.AES.encrypt(this.dataSource.password, secretKey,
                {iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.ZeroPadding}).toString();
            this.isTest = true;
          }
          doPost("/system/ds/testConnection", this.dataSource).then(resp => {
            if(resp.data.code === 200) {
              this.testConnectionResult = resp.data.message;
            } else {
              this.testConnectionResult = '测试不成功';
            }
          });
          this.dataSource.password = originalPassword;
        }
      })
    },

    // 提交数据
    dataSourceSubmit() {
      this.$refs.dataSourceRefForm.validate(valid => {
        if (valid) {
          // 验证通过，提交数据
          const originalPassword = this.dataSource.password;
          // 密码进行加密
          if(!this.dataSource.id || this.originalDataSource.password !== this.dataSource.password) {
            this.dataSource.password = CryptoJS.AES.encrypt(this.dataSource.password, secretKey,
                {iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.ZeroPadding}).toString();
          }
          if(this.dataSource.id > 0) {
            // 编辑操作
            doPut("/system/ds/update", this.dataSource).then(resp => {
              if(resp.data.code === 200) {
                // 编辑成功
                msgTip("编辑数据源成功","success");
                this.reload();
              } else {
                msgTip("编辑数据源失败","error")
              }
            });
          } else {
            // 新增操作
            doPost("/system/ds/add", this.dataSource).then(resp => {
              if(resp.data.code === 200) {
                // 新增成功
                msgTip("新增数据源成功","success");
                this.reload();
              } else if(resp.data.code === 903) {
                msgTip(resp.data.message, "error");
              } else  {
                msgTip("新增数据源失败","error");
              }
              this.dataSource.password = originalPassword;
            });
          }
        }
      });
    },

    /* 读取权限 */
    loadPermissions() {
      const permissionsJson = sessionStorage.getItem("permission");
      if (permissionsJson) {
        const permissionsArray = JSON.parse(permissionsJson);
        this.permissions = permissionsArray.reduce((acc, permission) => {
          acc[permission.code] = true;
          return acc;
        },{});
      }
    },
    /* 检查权限 */
    hasPermission(code) {
      return this.permissions[code] || false;
    }
  },
  mounted() {
    this.getData(1);
    this.loadPermissions();
  }
};
</script>

<style scoped>
.query-form {
  .el-input {
    width: 220px;
  }
  .el-select {
    width: 220px;
  }
}

.op-btn {
  margin-top: 20px;
  display: flex;
  justify-content: flex-start;
}

.custom-table {
  width: 100%;
  border-collapse: collapse;
  margin-top: 20px;
}
.custom-table ::v-deep th {
  background-color: rgb(190, 190, 190) ; /* 背景色 */
  color: #303133;
  font-weight: bold; /* 加粗字体 */
}

.custom-table ::v-deep th,
.custom-table ::v-deep td {
  padding: 10px;
  text-align: left;
}


.custom-table ::v-deep tr:nth-child(even) {
  background-color: #f9f9f9;
}

.custom-table ::v-deep tr:hover {
  background-color: #f1f1f1;
}


.pagination {
  margin-top: 20px;
}

.button-column {
  display: flex;
  flex-direction: column;
  gap: 5px; /* 设置按钮之间的间距 */
  .el-button {
    width: 80px;
    margin-left: 0 !important;
  }
}
</style>
